#pragma once

#include "fstream"
#include "nlohmann/json.hpp"
#include "point.hpp"
#include <unordered_map>

class PointTable : protected std::unordered_map<std::string, Point> {
public:
    using iterator = std::unordered_map<std::string, Point>::iterator;
    using const_iterator = std::unordered_map<std::string, Point>::const_iterator;

    iterator begin(void) { return std::unordered_map<std::string, Point>::begin(); }
    const_iterator begin(void) const { return std::unordered_map<std::string, Point>::begin(); }

    iterator end(void) { return std::unordered_map<std::string, Point>::end(); }
    const_iterator end(void) const { return std::unordered_map<std::string, Point>::end(); }

public:
    Point *findPoint(const std::string &name) {
        if (find(name) != end()) {
            return &operator[](name);
        }

        return nullptr;
    }

    friend void from_json(const nlohmann::json &j, PointTable &pt) {
        if (j.contains("points") && j.at("points").is_array()) {
            for (const auto &point : j.at("points")) {
                auto p = point.get<Point>();
                pt.insert(std::make_pair(p.name(), p));
            }
        }
    }

    bool fromFile(const std::string &profile) {
        std::ifstream ifs(profile);
        std::stringstream ss;
        if (ifs.is_open()) {
            ss << ifs.rdbuf();
        }

        if (!nlohmann::json::accept(ss.str())) {
            std::cerr << "bad file context" << std::endl;
            return false;
        }

        nlohmann::json::parse(ss.str()).get_to(*this);
        return true;
    }
};
